#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>

//pid_t ret = wait(int *status)
//pid_t ret = waitpid(int pid,int* status, int options)
//这里的status： 1. 输出型参数
//               2.int 是被当做几部分使用的


#define TASK_NUM 10

typedef void(*task_t)();
task_t tasks[TASK_NUM];

void task1()
{
    printf("这是打印日志的任务, pid:%d \n",getpid());
}

void task2()
{
    printf("只是检测网络健康状态的任务,pid: %d \n",getpid());

}

void task3()
{
    printf("绘制图形界面任务,pid: %d \n",getpid());
}
 

void InitTask()
{
    int i =0;
    for(;i<TASK_NUM;i++)
    {
        tasks[i] = NULL;
    }
}

int AddTask(task_t t)
{
    int i =0;//找到没有被使用的位置
    for(;i<TASK_NUM;i++)
    {
        if(tasks[i] == NULL)
            break;
    }
    if(i == TASK_NUM) return -1;//无法添加
    tasks[i] = t;
    return 0;//成功添加
}

void DelTask()
{}

void CheckTask()
{}

void UpdateTask()
{}

void ExecuteTask()//执行任务
{
    int i =0;
    for(i = 0;i < TASK_NUM;i++)
    {
        if(!tasks[i]) continue;
        tasks[i]();//调用方法
    }
}

int main()
{
    pid_t id = fork();
    if(id < 0)
    {
        printf("wrong\n");
    }
    else if(id == 0)
    {
        int cnt = 5;
        while(cnt--)
        {
            printf("i am a child , pid: %d, ppid:%d,cnt:%d \n",getpid(),getppid(),cnt);
            sleep(1);
        }
        //int a = 10/0;

        exit(11);
    }
    else
    {
//        int cnt = 10;
//        while(cnt--)
//        {
//            printf("i am parent, pid: %d, ppid: %d ,cnt:%d\n ",getpid(),getppid(),cnt);
//            sleep(1);
//        }

        //父亲进程拿子进程的状态数据，为什么必须使用wait等待？
        //进程具有独立性：如果以定义变量的形式，子进程和父进程是分开进行的，子进程的数据不会被父进程“看到”
        //waitpid
        //
        int status = 0;
        //pid_t ret = waitpid(-1,NULL,0);
        

        //添加任务
        InitTask();
        AddTask(task1);
        AddTask(task2);
        AddTask(task3);


        while(1)//轮询 - 循环 ，一直等
        {   
            //pid_t ret = waitpid(id,&status,0);//获取退出状态
            //等待的时候会检测id是否正确，只能检测自己的，否则等待失败
            
            //非阻塞
            pid_t ret = waitpid(id,&status,WNOHANG);
            if(ret > 0)
            {
               // printf("wait success：ret:%d ,status：%d \n",ret ,status);
             //   printf("wait success：ret:%d ,exit sig: %d,sxit code ：%d \n",ret ,status&0x7F,(status>>8)&0xFF);
  
                //进程等待 -- 用宏替换上面的输出
                if(WIFEXITED(status))
                {
                    printf("进程正常跑完，退出码：%d \n",WEXITSTATUS(status));
                }
                else
                {
                    printf("程序出异常了\n");
                }

                break; //轮询出结果 退出
  
                //拿到status 是256，为什么?
                //拿到status 是256，为什么?
                //0000 0001 0000 0000 后8位->是否收到信号->是否异常终止代码
                //前8位才是退出状态->运行了，出错了
                //
                
            }
            else if(ret < 0)
            {
                printf("失败\n");

                break; //出结果 -失败，也退出轮询
            }
            else
            {
                printf("子进程还没有退出，继续等待\n");//非阻塞轮询 测试
                ExecuteTask();
                usleep(10000);
          //      sleep(1);
            }
        }


    //    sleep(5);
    }

    return 0;
}
